package com.fadadianqi.logistics.search;

import com.fadadianqi.goods.model.Brand;
import com.fadadianqi.goods.model.Category;
import com.fadadianqi.goods.model.Goods;
import com.fadadianqi.goods.model.GoodsPropValue;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.search.AbstractIndexService;
import com.fadadianqi.search.IndexPathHelper;
import com.fadadianqi.search.IndexPathHelper.IndexEnum;
import com.yeqiangwei.commons.util.Pagination;
import com.yeqiangwei.commons.util.StringHelper;
import com.yeqiangwei.commons.util.ValidatorHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class GoodsIndexService extends AbstractIndexService {

    private static final Log log = LogFactory.getLog(GoodsIndexService.class);
    private static Boolean IS_RUNNING = Boolean.FALSE;
    private IndexPathHelper indexPathHelper = new IndexPathHelper(IndexEnum.GOODS);
    private String newPath;
    @Autowired
    private GoodsService goodsService;

    public GoodsIndexService() {

    }

    @Override
    public String getCurrentIndexPath() {
        return indexPathHelper.getIndexPath();
    }

    @Override
    protected String getNewIndexPath() {
        newPath = indexPathHelper.createNewPath();
        return newPath;
    }

    @Override
    protected void changeIndexPath() {
        indexPathHelper.savePath(newPath);
    }

    protected void build(IndexWriter writer, boolean rebuild) throws Exception {
        synchronized (writer) {
            // 写操作保持同步
            int total = 0;
            if (rebuild) {
                total = goodsService.countAll();
            } else {
                total = goodsService.countAllNotIndexed();
            }
            int limit = 1000;
            int pages = total / limit;
            if (total % limit != 0) {
                pages++;
            }
            for (int page = 1; page <= pages; page++) {
                Pagination pagination = null;
                List<Goods> list = null;
                if (rebuild) {
                    pagination = new Pagination(page, limit);
                    list = goodsService.findAll(pagination);
                } else {
                    pagination = new Pagination(1, limit);
                    list = goodsService.findAllNotIndexed(pagination);
                }
                if (ValidatorHelper.isEmpty(list)) {
                    continue;
                }
                for (Goods goods : list) {
                    writer.addDocument(documentBuilder(goods));
                    goods.setIndexed(Boolean.TRUE);
                    goodsService.updateGoodsIndexed(goods);
                }
            }
            writer.optimize();
            writer.close(true);
        }
    }

    public synchronized boolean isRunning() {
        return IS_RUNNING;
    }

    protected synchronized void lock() {
        IS_RUNNING = true;
    }

    protected synchronized void unlock() {
        IS_RUNNING = false;
    }

    /**
     *
     */
    @Override
    protected Document documentBuilder(Object o) throws Exception {
        Goods goods = (Goods) o;
        Brand brand = goodsService.getBrandById(goods.getBrandId());
        Category category = goodsService.getCategoryById(goods.getCategoryId());

        Document doc = new Document();

        Field id = new Field(Goods.PROP_ID, goods.getId(), Store.YES, Index.NOT_ANALYZED);
        doc.add(id);

        Field brandId = new Field(Goods.PROP_BRAND_ID, goods.getBrandId(), Store.YES, Index.ANALYZED);
        doc.add(brandId);

        Field categoryId = new Field(Goods.PROP_CATEGORY_ID, goods.getCategoryId(), Store.YES, Index.ANALYZED);
        doc.add(categoryId);

        Field name = new Field(Goods.PROP_BRAND_NAME, goods.getName(), Store.YES, Index.ANALYZED);
        doc.add(name);

        Field displayName = new Field(Goods.PROP_DISPLAY_NAME, goods.getDisplayName(), Store.YES, Index.ANALYZED);
        doc.add(displayName);

        Field brandName = new Field(Goods.PROP_BRAND_NAME, brand.getName(), Store.YES, Index.ANALYZED);
        doc.add(brandName);

        Field categoryName = new Field(Goods.PROP_CATEGORY_NAME, category.getName(), Store.YES, Index.ANALYZED);
        doc.add(categoryName);

        StringBuilder pinyin = new StringBuilder();
        pinyin.append(StringHelper.toPinyin(goods.getName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(goods.getName()));
        pinyin.append(" ");
        pinyin.append(StringHelper.toPinyin(goods.getDisplayName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(goods.getDisplayName()));
        pinyin.append(" ");
        pinyin.append(StringHelper.toPinyin(brand.getName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(brand.getName()));
        pinyin.append(" ");
        pinyin.append(StringHelper.toPinyin(category.getName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(category.getName()));

        Field pinyinField = new Field("pinyin", pinyin.toString(), Store.YES, Index.ANALYZED);
        doc.add(pinyinField);

        StringBuilder props = new StringBuilder();
        List<GoodsPropValue> pvs = goodsService.findGoodsPropValueByGoodsId(goods.getId());
        if (ValidatorHelper.isNotEmpty(pvs)) {
            for (GoodsPropValue v : pvs) {
                String val = v.getPropValueName();
                props.append(val);
                props.append(" ");
            }
        }
        Field propsField = new Field("props", props.toString(), Store.YES, Index.ANALYZED);
        doc.add(propsField);

        if (log.isDebugEnabled()) {
            log.debug("#documentBuilder# " + doc.toString());
        }
        return doc;
    }

}

